import mongoose from 'mongoose';
import { User, IUser } from '../models/user';

/**
 * 用户数据访问对象
 * 提供用户相关的数据库操作方法
 */
export class UserDAO {
  /**
   * 创建新用户
   * @param userData 用户数据
   * @returns 创建的用户文档
   */
  async create(userData: Partial<IUser>): Promise<IUser> {
    try {
      const user = new User(userData);
      return await user.save();
    } catch (error: any) {
      if (error.code === 11000) {
        // 处理唯一性约束错误
        const field = Object.keys(error.keyPattern)[0];
        throw new Error(`${field} already exists`);
      }
      throw error;
    }
  }

  /**
   * 根据ID查找用户
   * @param id 用户ID
   * @returns 用户文档或null
   */
  async findById(id: mongoose.Types.ObjectId | string): Promise<IUser | null> {
    try {
      if (!mongoose.Types.ObjectId.isValid(id)) {
        throw new Error('Invalid user ID format');
      }
      return await User.findById(id).exec();
    } catch (error) {
      throw error;
    }
  }

  /**
   * 根据用户名查找用户
   * @param username 用户名
   * @returns 用户文档或null
   */
  async findByUsername(username: string): Promise<IUser | null> {
    try {
      return await User.findByUsername(username);
    } catch (error) {
      throw error;
    }
  }

  /**
   * 根据邮箱查找用户
   * @param email 邮箱地址
   * @returns 用户文档或null
   */
  async findByEmail(email: string): Promise<IUser | null> {
    try {
      return await User.findByEmail(email);
    } catch (error) {
      throw error;
    }
  }

  /**
   * 更新用户信息
   * @param id 用户ID
   * @param updateData 更新数据
   * @returns 更新后的用户文档或null
   */
  async update(
    id: mongoose.Types.ObjectId | string,
    updateData: Partial<IUser>
  ): Promise<IUser | null> {
    try {
      if (!mongoose.Types.ObjectId.isValid(id)) {
        throw new Error('Invalid user ID format');
      }

      // 移除不应该被更新的字段
      const { _id, createdAt, ...safeUpdateData } = updateData as any;
      
      // 设置更新时间
      safeUpdateData.updatedAt = new Date();

      const updatedUser = await User.findByIdAndUpdate(
        id,
        safeUpdateData,
        { 
          new: true, 
          runValidators: true,
          lean: false
        }
      ).exec();

      return updatedUser;
    } catch (error: any) {
      if (error.code === 11000) {
        // 处理唯一性约束错误
        const field = Object.keys(error.keyPattern)[0];
        throw new Error(`${field} already exists`);
      }
      throw error;
    }
  }

  /**
   * 删除用户
   * @param id 用户ID
   * @returns 是否删除成功
   */
  async delete(id: mongoose.Types.ObjectId | string): Promise<boolean> {
    try {
      if (!mongoose.Types.ObjectId.isValid(id)) {
        throw new Error('Invalid user ID format');
      }

      const result = await User.findByIdAndDelete(id).exec();
      return result !== null;
    } catch (error) {
      throw error;
    }
  }

  /**
   * 根据组织结构查找用户
   * @param criteria 查询条件
   * @returns 用户文档数组
   */
  async findByOrganization(criteria: {
    teamId?: mongoose.Types.ObjectId | string;
    departmentId?: mongoose.Types.ObjectId | string;
    groupId?: mongoose.Types.ObjectId | string;
  }): Promise<IUser[]> {
    try {
      const query: any = {};
      
      if (criteria.teamId) {
        if (!mongoose.Types.ObjectId.isValid(criteria.teamId)) {
          throw new Error('Invalid team ID format');
        }
        query.teamId = criteria.teamId;
      }
      
      if (criteria.departmentId) {
        if (!mongoose.Types.ObjectId.isValid(criteria.departmentId)) {
          throw new Error('Invalid department ID format');
        }
        query.departmentId = criteria.departmentId;
      }
      
      if (criteria.groupId) {
        if (!mongoose.Types.ObjectId.isValid(criteria.groupId)) {
          throw new Error('Invalid group ID format');
        }
        query.groupId = criteria.groupId;
      }

      return await User.find(query).exec();
    } catch (error) {
      throw error;
    }
  }

  /**
   * 批量创建用户
   * @param usersData 用户数据数组
   * @returns 创建的用户文档数组
   */
  async batchCreate(usersData: Partial<IUser>[]): Promise<IUser[]> {
    try {
      if (!Array.isArray(usersData) || usersData.length === 0) {
        return [];
      }
      
      const createdUsers = await User.insertMany(usersData);
       return createdUsers as IUser[];
    } catch (error: any) {
      if (error.code === 11000) {
        // 处理批量插入时的唯一性约束错误
        throw new Error('Duplicate key error in batch create operation');
      }
      throw error;
    }
  }

  /**
   * 更新用户状态
   * @param id 用户ID
   * @param status 新状态
   * @returns 更新后的用户文档或null
   */
  async updateStatus(
    id: mongoose.Types.ObjectId | string,
    status: 'active' | 'inactive' | 'disabled'
  ): Promise<IUser | null> {
    try {
      if (!mongoose.Types.ObjectId.isValid(id)) {
        throw new Error('Invalid user ID format');
      }

      // 验证状态值
      const validStatuses = ['active', 'inactive', 'disabled'];
      if (!validStatuses.includes(status)) {
        throw new Error(`Invalid status value. Must be one of: ${validStatuses.join(', ')}`);
      }

      const updatedUser = await User.findByIdAndUpdate(
        id,
        { 
          status,
          updatedAt: new Date()
        },
        { 
          new: true, 
          runValidators: true,
          lean: false
        }
      ).exec();

      return updatedUser;
    } catch (error) {
      throw error;
    }
  }

  /**
   * 根据多个条件查找用户（分页支持）
   * @param criteria 查询条件
   * @param options 查询选项
   * @returns 用户文档数组和总数
   */
  async findWithPagination(
    criteria: {
      username?: string;
      email?: string;
      realName?: string;
      status?: string;
      teamId?: mongoose.Types.ObjectId | string;
      departmentId?: mongoose.Types.ObjectId | string;
      groupId?: mongoose.Types.ObjectId | string;
    },
    options: {
      page?: number;
      limit?: number;
      sort?: string;
      select?: string;
    } = {}
  ): Promise<{ users: IUser[]; total: number; page: number; totalPages: number }> {
    try {
      const {
        page = 1,
        limit = 10,
        sort = '-createdAt',
        select = '-password'
      } = options;

      const query: any = {};
      
      // 构建查询条件
      if (criteria.username) {
        query.username = new RegExp(criteria.username, 'i');
      }
      
      if (criteria.email) {
        query.email = new RegExp(criteria.email, 'i');
      }
      
      if (criteria.realName) {
        query.realName = new RegExp(criteria.realName, 'i');
      }
      
      if (criteria.status) {
        query.status = criteria.status;
      }
      
      if (criteria.teamId) {
        query.teamId = criteria.teamId;
      }
      
      if (criteria.departmentId) {
        query.departmentId = criteria.departmentId;
      }
      
      if (criteria.groupId) {
        query.groupId = criteria.groupId;
      }

      const skip = (page - 1) * limit;
      
      const [users, total] = await Promise.all([
        User.find(query)
          .select(select)
          .sort(sort)
          .skip(skip)
          .limit(limit)
          .exec(),
        User.countDocuments(query).exec()
      ]);

      const totalPages = Math.ceil(total / limit);

      return {
        users,
        total,
        page,
        totalPages
      };
    } catch (error) {
      throw error;
    }
  }
}

export default UserDAO;